/*
 * TacticaVergui.java
 *
 * Created on 16 de abril de 2006, 20:10
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package futbol.tacticas.concursantes2007.cdvergui;

import futbol.General;
//import futbol.Partido;
import futbol.tacticas.*;
import futbol.tacticas.concursantes.Tactica;

import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.Vector;



class Marcador {
    
    private int misGoles;
    
    private int susGoles;
    
    private double ultimaX;
    
    /** Creates a new instance of Marcador */
    public Marcador() {

    }
    
    public void ejecutar (Point bola) {
        double x = bola.getX();
        double y = bola.getY();
        
        if (Math.abs(y)<30) {
            if (this.ultimaX>150 && x<40) {
                this.misGoles++;
                //System.out.println("GOOOOL del equipo local!!! :D (" + x + ", " + y + ")");
                this.mostrarMarcador();
            } else if (this.ultimaX<-150 && x>-40) {
                this.susGoles++;
                //System.out.println("GOOOOL del equipo visitante!!! :( (" + x + ", " + y + ")");
                this.mostrarMarcador();
            }
        }
        
        this.ultimaX = x;
        
    }
    
    public void mostrarMarcador () {
        //System.out.println(" --------------------------");
        //System.out.println("|   YO       vs       T   |");
        //System.out.println("|   " + this.getMisGoles() + "       vs       " + this.getSusGoles() + "   |");
        //System.out.println(" --------------------------");
    }

    public int getMisGoles() {
        return misGoles;
    }

    public void setMisGoles(int misGoles) {
        this.misGoles = misGoles;
    }

    public int getSusGoles() {
        return susGoles;
    }

    public void setSusGoles(int susGoles) {
        this.susGoles = susGoles;
    }
    
}


/**
 *
 * @author Administrador
 */
public class TacticaVergui implements Tactica{
    
    private int nValores[][]={
        {-145,0,7}, // Portero [1]
        
        {-75,85,7}, // Lateral Derecho [2]
        {-75,-85,7}, // Lateral Izquierdo [3]
        {-80,30,7}, // Central Derecho [4]
        {-80,-30,7}, // Central Izquierdo [5]
        
        {-20,-30,7}, // Doble Pivote (D) [6]
        {-20,30,7}, // Doble Pivote (I) [7]
        
        {25,75,7}, // Extremo Derecho [8]
        {100,10,7}, // Delantero Centro [9]
        {50,-10,7}, // Mediapunta [10]
        {25,-75,7}  // Extremo Derecho [11]
    };
    
    Marcador marcador;
    
    public TacticaVergui () {
        this.marcador = new Marcador();
    }

    public String getNombre(){
        return "c.d. vergui";
    }
    
    public Color getColor1(){
        return Color.BLUE;
    }
    
    public Color getColor2(){
        return Color.BLACK;
    }
    
    public Color getColorNumero(){
        return Color.CYAN;
    }
    
    public int getFuerza(int n){
        return nValores[n][2];
    }
    
    public int getXInicial(int n){
        return nValores[n][0];
    }
    
    public int getYInicial(int n){
        return nValores[n][1];
    }
    
    public Vector<Comando> getComandos(SituacionJugadores sj){
        Vector<Comando> comandos=new Vector();

        Point bola = sj.getBola();
        this.porterear(sj, comandos);
        if (bola.x>0 || this.tengoLaBola(sj)) this.atacar(sj, comandos);
        else this.defender(sj, comandos);
        
        this.marcador.ejecutar(bola);
        
        return comandos;
    }
    
    
    
    private void porterear (SituacionJugadores sj, Vector<Comando> comandos) {
        //----------------------------------------------------------------------
        Point bola = sj.getBola();
        //---------------------------
        // Movimientos del Portero
        //---------------------------
        double x = nValores[0][0];
        if (bola.getX()>-90) x = x + 10;
        double y = bola.getY();
        if (y<-25) y=-25;
        if (y>25) y=25;
        
        /*x = this.nValores[0][0] + Math.abs(bola.x%50);
        y = bola.y%30;*/

        comandos.add(new ComandoIrA(0, x, y));
        double ydisparo = 80;
        if (sj.getContrarioMasCerca(bola.x, bola.y)>0) ydisparo = -80;
        comandos.add(new ComandoTiroAPuerta(0, (int) ydisparo));
        //----------------------------------------------------------------------
    }
    
    private void defender (SituacionJugadores sj, Vector<Comando> comandos) {
        //System.out.println("Defendiendo...");
        this.cambiarTactica(2);
        
        Point bola = sj.getBola();
        
        // ---------------------------
        // Juego en equipo
        // ---------------------------
        double mvx = (bola.x<0)?bola.x*0.20:bola.x*0.10;
        double mvy = bola.y*0.10;
        Point[] misJugadores = sj.getMisJugadores();
        
        int maxJugadoresPresionando = 1;
        if (bola.x>35) maxJugadoresPresionando = 2;
        
        List js0 = this.misJugadoresOrdenadosPorCercania(sj);
        for (int n=1; n<misJugadores.length; n++) {                
            if (js0.indexOf(new Integer(n))>0) {
                
                if (n<maxJugadoresPresionando) {
                    comandos.add(new ComandoIrA(n, bola.x, bola.y));
                } else {
                    comandos.add(new ComandoIrA(n, nValores[n][0] + mvx, nValores[n][1] + mvy));
                }
                                
            }
            
            this.chutar (n, sj, comandos);
            
        }
        

        
    }
    
    private void atacar (SituacionJugadores sj, Vector<Comando> comandos) {
        this.cambiarTactica(2);
        
        Point bola = sj.getBola();
        double mvx = (bola.x<0)?bola.x*0.15:bola.x*0.15;
        double mvy = bola.y*0.10;
        
        int jugadoresPresionando = 2;
        if (bola.x>35) jugadoresPresionando = 4;
        
        List js = this.misJugadoresOrdenadosPorCercania(sj);
        for (int i=0; i<js.size(); i++) {
            int jugador = (Integer)js.get(i);
            Point puntoJugador = sj.getMisJugadores()[jugador];
            if (i<jugadoresPresionando) {
                comandos.add(new ComandoIrA (jugador, bola.x, bola.y));
                this.chutar (jugador, sj, comandos);
                /*
                if (puntoJugador.x>50) {
                    System.out.println("x>50...");
                    this.chutar (jugador, sj, comandos);
                } else if (puntoJugador.x>-50) {
                    System.out.println("x>0...");                    
                    this.chutar (jugador, sj, comandos);
                } else {
                    System.out.println("x<0...");
                    this.pasarAlJugadorMasDesmarcado(jugador, sj, comandos);
                    //this.regatear(jugador, sj, comandos);
                    this.chutar (jugador, sj, comandos);
                }
                */
            } else {
                comandos.add(new ComandoIrA (jugador, this.nValores[jugador][0] + mvx, this.nValores[jugador][1] + mvy));
                this.chutar (jugador, sj, comandos);
            }

        }//for i
        
    }
    
    
    
    private void chutar (int jugador, SituacionJugadores sj, Vector<Comando> comandos) {
        int desvio = 0;
        /*if (sj.getMisJugadores()[jugador].x>30) {
            Point porterorival = sj.getContrario()[0];
            
            //int desvio = -porterorival.y;
            if (porterorival.y<0) desvio = 30;
            else desvio = -30;
        }*/
        comandos.add(new ComandoTiroAPuerta (jugador, desvio));
    }
    
    private void pasarAlJugadorMasDesmarcado (int jugador, SituacionJugadores sj, Vector<Comando> comandos) {
        int[] excluir = {jugador};
        comandos.add(new ComandoPase(jugador, this.jugadorMasDesmarcado(sj, excluir)));
    }
    
    private void centrar (int jugador1, int jugador2, SituacionJugadores sj, Vector<Comando> comandos) {
        
    }
    
    private void regatear (int jugador, SituacionJugadores sj, Vector<Comando> comandos) {
        double distanciaPaso = 10;
        double distanciaParaAvanzar = 50;
        while (distanciaParaAvanzar>0) {
            int contrarioParaRegatear = sj.getContrarioMasCerca(jugador);
            int regateY = 0;
            regateY = -sj.getContrario()[contrarioParaRegatear].y;
            comandos.add(new ComandoGolpearBola(jugador, sj.getMisJugadores()[jugador].x+distanciaPaso, regateY));
            comandos.add(new ComandoIrA(jugador, sj.getMisJugadores()[jugador].x+distanciaPaso, regateY));
            distanciaParaAvanzar-=distanciaPaso;
        }
    }
    
    
    /**
     * Busca mi jugador ms desmarcado.
     *
     * @param SituacionJugadores sj
     * @return int ndice de mi jugador ms desmarcado
     */
    private int jugadorMasDesmarcado (SituacionJugadores sj, int[] excluir) {
        double mayorDistancia = 0;
        int jugadorMasDesmarcado = 8; // Por defecto ponemos al delantero centro
        for (int i=1; i<sj.getMisJugadores().length; i++) {
            if (Arrays.binarySearch(excluir, i)>=0) continue;
            Point miJugador = sj.getMisJugadores()[i];
            Point contrarioMasCercaDeMiJugador = sj.getContrario()[sj.getContrarioMasCerca(i)];
            double distancia = General.getDistancia(miJugador.x, miJugador.y,
                    contrarioMasCercaDeMiJugador.x, contrarioMasCercaDeMiJugador.y);
            if (distancia>mayorDistancia) {
                mayorDistancia = distancia;
                jugadorMasDesmarcado = i;
            }
        }// for i
        return jugadorMasDesmarcado;
    }
    
    /**
     * Devuelve una lista con los ndices de mis jugadores ordenador por
     * cercana a la bola.
     *
     * @param SituacionJugadores sj
     * @return List mis jugadores ordenados por cercana.
     */
    private List misJugadoresOrdenadosPorCercania (SituacionJugadores sj) {

        Map jugadores = new HashMap ();
        Point[] points = sj.getMisJugadores();
        //System.out.println("POINTS: " + points);
        
        Point bola = sj.getBola();
        
        for (int i=1; i<points.length; i++) {
            Point point = points[i];
            double distancia = General.getDistancia(bola.x, bola.y, point.x, point.y);
            Double d = new Double(distancia);
            while (jugadores.containsKey(d)) d = d + 0.0000000001;
            jugadores.put(d, new Integer(i));
            //System.out.println("put " + d + ", " + new Integer(i));
        }//for i

        //System.out.println("JUGADORES: " + jugadores);
        
        List l = new ArrayList(jugadores.keySet());
        Collections.sort(l);
        //System.out.println("L: " + l);
        
        List out = new ArrayList();
        for (int i=0; i<l.size(); i++) {
            //System.out.println("l.get(" + i + ")==" + l.get(i) + l.get(i).getClass().getName());
            Double d = (Double) l.get(i);
            Integer j = (Integer) jugadores.get(d);
            out.add(j);
        }//for i
        
        
        /*
        Iterator it = jugadores.keySet().iterator();
        while (it.hasNext()) {
            Double d = (Double) it.next();
            Integer i = (Integer) jugadores.get(d);
            l.add(i);
        }
         */
        //List l = new ArrayList(jugadores.entrySet());
        //System.out.println(out);
        return out;
    }
        
    /**
     * Comprueba si un jugador se encuentra dentro del rea contraria.
     *
     * @param SituacionJugadores sj
     * @param int j
     * @return boolean
     */
    public boolean dentroDelAreaContraria (SituacionJugadores sj, int j) {
        Point jugador = sj.getMisJugadores()[j];
        return this.dentroDelAreaContraria(jugador);
    }
    
    /**
     * Comprueba si el punto "point" se encuentra dentro del rea contraria.
     *
     * @return boolean
     */
    public boolean dentroDelAreaContraria (Point point) {
        if (point.x>110 && Math.abs(point.y)<70) return true;
        else return false;
    }
    
    /**
     * Comprueba si un jugador se encuentra dentro de mi rea.
     *
     * @param SituacionJugadores sj
     * @param int j
     * @return boolean
     */
    public boolean dentroDelAreaPropia (SituacionJugadores sj, int j) {
        Point jugador = sj.getMisJugadores()[j];
        return this.dentroDelAreaContraria(jugador);
    }
    
    /**
     * Comprueba si el punto "point" se encuentra dentro de mi rea.
     *
     * @return boolean
     */
    public boolean dentroDelAreaPropria (Point point) {
        if (point.x<-110 && Math.abs(point.y)<70) return true;
        else return false;
    }
    
    /** 
     * Comprueba si alguno de mis jugadores tiene la bola,
     * en otras palabras, comprueba si el jugador ms cercano es de mi equipo.
     * 
     * @return boolean
     */
    public boolean tengoLaBola (SituacionJugadores sj) {
        Point bola = sj.getBola();
        
        Point miJugadorMasCercanoALaBola = sj.getMisJugadores()[sj.getMasCercanoDeBola()];
        Point suJugadorMasCercanoALaBola = sj.getContrario()[sj.getContrarioMasCerca(bola.x, bola.y)];
        
        double miDistancia = General.getDistancia(bola.x, bola.y, miJugadorMasCercanoALaBola.x, miJugadorMasCercanoALaBola.y);
        
        double suDistancia = General.getDistancia(bola.x, bola.y, suJugadorMasCercanoALaBola.x, suJugadorMasCercanoALaBola.y);
        
        return (miDistancia<suDistancia);
    }

    /**
     * Cambia de tctica segn el parmetro tactica
     *  0: 4-2-3-1
     *  1: 4-2-2
     *  2: 4-3-3
     *  3: 3-3-3-1
     *
     * @param int tactica
     */
    public void cambiarTactica (int tactica) {
        switch (tactica) {
            case 0: //(4-2-3-1)
                this.nValores[1][0] = -75;
                this.nValores[1][1] = 85;
                
                this.nValores[2][0] = -75;
                this.nValores[2][1] = -85;
                
                this.nValores[3][0] = -80;
                this.nValores[3][1] = 30;
                
                this.nValores[4][0] = -80;
                this.nValores[4][1] = -30;
                
                
                this.nValores[5][0] = -20;
                this.nValores[5][1] = -30;
                
                this.nValores[6][0] = -20;
                this.nValores[6][1] = +30;
                
                
                this.nValores[7][0] = 25;
                this.nValores[7][1] = 75;
                
                this.nValores[8][0] = 100;
                this.nValores[8][1] = 0;
                
                this.nValores[9][0] = 50;
                this.nValores[9][1] = 0;
                
                this.nValores[10][0] = 25;
                this.nValores[10][1] = -75;
                
                break;
                
            case 1: //(4-4-2)
                this.nValores[1][0] = -75;
                this.nValores[1][1] = 85;
                
                this.nValores[2][0] = -75;
                this.nValores[2][1] = -85;
                
                this.nValores[3][0] = -80;
                this.nValores[3][1] = 30;
                
                this.nValores[4][0] = -80;
                this.nValores[4][1] = -30;
                
                
                this.nValores[5][0] = -20;
                this.nValores[5][1] = -20;
                
                this.nValores[6][0] = -20;
                this.nValores[6][1] = +20;
                
                
                this.nValores[7][0] = 25;
                this.nValores[7][1] = 75;
                
                this.nValores[8][0] = 100;
                this.nValores[8][1] = -25;
                
                this.nValores[9][0] = 100;
                this.nValores[9][1] = 25;
                
                this.nValores[10][0] = 25;
                this.nValores[10][1] = -75;
                
                break;
                
            case 2: //(4-3-3)
                this.nValores[1][0] = -75;
                this.nValores[1][1] = 70;
                
                this.nValores[2][0] = -75;
                this.nValores[2][1] = -70;
                
                this.nValores[3][0] = -80;
                this.nValores[3][1] = 20;
                
                this.nValores[4][0] = -80;
                this.nValores[4][1] = -20;
                
                
                this.nValores[5][0] = 0;
                this.nValores[5][1] = 0;
                
                this.nValores[6][0] = 25;
                this.nValores[6][1] = -70;
                
                this.nValores[7][0] = 25;
                this.nValores[7][1] = +70;

                
                
                this.nValores[8][0] = 90;
                this.nValores[8][1] = +0;
                
                this.nValores[9][0] = 90;
                this.nValores[9][1] = 50;
                
                this.nValores[10][0] = 90;
                this.nValores[10][1] = -50;
                
                break;
                
                
            case 3: //(3-3-3-1)
                // --------------------------
                // Defensa de 3
                // --------------------------
                this.nValores[1][0] = -75;
                this.nValores[1][1] = 35;

                this.nValores[3][0] = -80;
                this.nValores[3][1] = 0;

                this.nValores[2][0] = -75;
                this.nValores[2][1] = -35;
                
                
                
                
                // --------------------------
                // Centro del campo con 3 hombres
                // --------------------------
                this.nValores[5][0] = -15;
                this.nValores[5][1] = +35;

                this.nValores[4][0] = -20;
                this.nValores[4][1] = 0;
                
                this.nValores[6][0] = -15;
                this.nValores[6][1] = -35;
                
                
                
                
                // --------------------------
                // 3 mediapuntas
                // --------------------------                
                
                this.nValores[7][0] = 80;
                this.nValores[7][1] = +30;
                
                this.nValores[9][0] = 75;
                this.nValores[9][1] = 0;
                
                this.nValores[10][0] = 80;
                this.nValores[10][1] = -30;

                
                // --------------------------
                // 1 delantero centro
                // --------------------------  
                this.nValores[8][0] = 100;
                this.nValores[8][1] = +0;

                break;
        }//switch

    }

}
